/**
 * File		: RubixCubeRenderer.java
 * Subject	: Renders the cube on screen
 * Author	: Isaac Parenteau (locus2k@gmail.com)
 * Date		: April 16th, 2011
 */
package src.project.rubix;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import src.project.cube.World;
import src.project.util.Camera;
import src.project.util.Vector3;

import android.opengl.GLSurfaceView;

public class RubixCubeRenderer implements GLSurfaceView.Renderer{

	/**
	 *Interface to animate our cube
	 */
	public interface AnimationCallback{
		void animate();
	}
	
	
	private World world;
	private float xRotation = 0;
	private float yRotation = 0;
	
	private GL10 currentGL;
	private int height;
	private Camera camera;
	
	private AnimationCallback callback;
	
	public RubixCubeRenderer(World world, AnimationCallback callback){
		this.world = world;
		this.callback = callback;
	}
	
	@Override
	public void onDrawFrame(GL10 gl) {
		
		if(callback != null)
			callback.animate();
		
		currentGL = gl;
		gl.glClearColor(0.5f,0.5f,0.5f,1);
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();
        
        
        gl.glTranslatef(0, 0, -3.0f);
        gl.glScalef(0.5f, 0.5f, 0.5f);
        gl.glRotatef(yRotation, 0, 1, 0);
        gl.glRotatef(xRotation, 1, 0, 0);

        gl.glColor4f(0.7f, 0.7f, 0.7f, 1.0f);
        world.draw(gl);
	}

	@Override
	public void onSurfaceChanged(GL10 gl, int width, int height) {
		this.height = height;

		gl.glViewport(0, 0, width, height);
		float ratio = (float)width / height;
        
        camera = new Camera(gl,-ratio, ratio, 1, -1, 2, 12,
        		new Vector3(0, 0, -1f), Vector3.Zero, Vector3.Up);
        camera.createCamera();

        gl.glDisable(GL10.GL_DITHER);
        gl.glActiveTexture(GL10.GL_TEXTURE0);
		
	}

	@Override
	public void onSurfaceCreated(GL10 gl, EGLConfig config) {
		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
        gl.glEnable(GL10.GL_CULL_FACE);
        gl.glShadeModel(GL10.GL_SMOOTH);
        gl.glEnable(GL10.GL_DEPTH_TEST);
        gl.glEnable(GL10.GL_BLEND);
        gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
	}
	
	/**
	 * Updates the x rotation value
	 * @param rotationX
	 */
	public void updateXRotation(float rotationX){
		xRotation += rotationX;
	}
	
	/**
	 * Updates the y rotation value
	 * @param rotationY
	 */
	public void updateYRotation(float rotationY){
		yRotation += rotationY;
	}
	
	/**
	 * Gets the pixels at a specific screen coordinate
	 * @param x x screen coordinate
	 * @param y y screen coordinate
	 * @return
	 */
	public byte[] getPixels(float x, float y) {
		ByteBuffer pixelBuffer = ByteBuffer.allocateDirect(4);
		pixelBuffer.order(ByteOrder.nativeOrder());
		
		currentGL.glReadPixels((int)x, height-(int)y, 1, 1, 
				GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, pixelBuffer);
		byte b[] = new byte[4];
		pixelBuffer.get(b);
		return b;
	}
}
